package com.atguigu.spzx.manager.service.impl;

import cn.hutool.core.convert.impl.MapConverter;
import com.atguigu.spzx.common.exception.GuiguException;
import com.atguigu.spzx.common.util.LoginAuthUtil;
import com.atguigu.spzx.manager.mapper.SysMenuMapper;
import com.atguigu.spzx.manager.mapper.SysRoleMenuMapper;
import com.atguigu.spzx.manager.service.SysMenuService;
import com.atguigu.spzx.model.entity.system.SysMenu;
import com.atguigu.spzx.model.entity.system.SysUser;
import com.atguigu.spzx.model.vo.common.ResultCodeEnum;
import com.atguigu.spzx.model.vo.system.MenuVo;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author syh
 * @create 2023-08-19 9:56
 */
@Service
public class SysMenuServiceImpl implements SysMenuService {
    @Resource
    SysMenuMapper sysMenuMapper;
    @Resource
    SysRoleMenuMapper sysRoleMenuMapper;

    @Override
    public List<SysMenu> findNodes() {
        List<SysMenu> menus=sysMenuMapper.selectAllMenus();
        //如果一个menu的parentId的值为0就表示他是父菜单
        //一级菜单集合
        List<SysMenu> parentMenus = menus.stream().filter(sysMenu -> sysMenu.getParentId().longValue() == 0).collect(Collectors.toList());
        buildMenuTree(parentMenus,menus);//最终所有的菜单级联关系的数据都绑定到一级菜单上
        return parentMenus;
    }

    @Override
    public void deleteById(Long id) {
        long count=sysMenuMapper.selectChildCount(id);
        if (count>0){
            throw new GuiguException(ResultCodeEnum.HAS_CHILDREN_ERROR);
        }
        sysMenuMapper.deleteById(id);
    }

    @Override
    public SysMenu getById(Long id) {
        return sysMenuMapper.getById(id);
    }

    @Override
    public void updateById(SysMenu sysMenu) {
        sysMenu.setUpdateTime(new Date());
        sysMenuMapper.updateById(sysMenu);
    }

    @Override
    public void save(SysMenu sysMenu) {
        sysMenu.setCreateTime(new Date());
        sysMenu.setUpdateTime(new Date());
        sysMenuMapper.save(sysMenu);
    }

    @Override
    public Map<String, Object> listRoleMenus(Long roleId) {
       //1.查询所有可用的菜单
        List<SysMenu> menus = sysMenuMapper.selectAllMenus().stream().filter(sysMenu -> sysMenu.getStatus().intValue() == 1).collect(Collectors.toList());

        //2.组装为父子菜单集合
        List<SysMenu> parents = menus.stream().filter(sysMenu -> sysMenu.getParentId().longValue() == 0).collect(Collectors.toList());
        buildMenuTree(parents,menus);
        //3.查询角色已分配的菜单id集合:sys_role_menu表就可以了
        List<Long> checkedMenuIds=sysRoleMenuMapper.selectCheckedMenuIdsByRoleId(roleId);


        Map<String,Object> map=new HashMap<>();
        map.put("menus",parents);
        map.put("checkedMenuIds",checkedMenuIds);
        return map;

    }

    @Override
    public List<MenuVo> listMenusByLoginUserId() {
        //1.获取登录用户的id
        SysUser sysUser = LoginAuthUtil.get();
        //2.查询当前用户的角色拥有的菜单列表封装为MenuVo对象的嵌套集合,多表联查，最终查菜单
        //因为数据需要组装为父子关系的集合，查询的数据必须携带parent_id
        List<SysMenu> sysMenus=sysMenuMapper.selectMenusByLoginUserId(sysUser.getId());
        //组装数据，考虑两级 菜单
        List<MenuVo> menuVoList = sysMenus.stream().filter(parent -> parent.getParentId().longValue() == 0)
                //如果数据集合，每个元素需要转为另一个类型的值/对象 可以使用map处理
                .map(parent -> {//封装1级菜单对象
                    MenuVo menuVo = new MenuVo();
                    menuVo.setName(parent.getComponent());
                    menuVo.setTitle(parent.getTitle());
                    //使用一级菜单的id当做父id从sysMenus中查询它的下一级菜单集合
                    List<MenuVo> childMenuVos = sysMenus.stream().filter(child -> child.getParentId().longValue() == parent.getId().longValue())
                            .map(child -> {
                                MenuVo childMenuVo = new MenuVo();
                                childMenuVo.setChildren(null);
                                childMenuVo.setName(child.getComponent());
                                childMenuVo.setTitle(child.getTitle());
                                return childMenuVo;
                            }).collect(Collectors.toList());
                    menuVo.setChildren(childMenuVos);
                    //返回一个组装好的一级菜单和他组装好的二级菜单的集合的对象
                    return menuVo;
                })
                //将map返回的每个一级菜单对象封装到list集合中
                .collect(Collectors.toList());
        return menuVoList;
    }

    private void buildMenuTree(List<SysMenu> parentMenus, List<SysMenu> menus) {
            if (CollectionUtils.isEmpty(parentMenus)||CollectionUtils.isEmpty(menus)){
                return;
            }
            //遍历父菜单
            parentMenus.forEach(parent->{
                List<SysMenu> children = menus.stream().filter(menu -> parent.getId().longValue() == menu.getParentId().longValue()).collect(Collectors.toList());
                parent.setChildren(children);
                buildMenuTree(children,menus);
            });
    }
}
